/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package snake;


import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * @author Administrator
 */
public class MainCanvas extends Canvas implements Runnable, ActionListener, KeyListener {


    private int current_x;

    private int current_y;

    private GameStatus gameStatus;

    public java.util.List<SnakePoint> snakeList = new ArrayList<SnakePoint>();

    public java.util.List<SnakePoint> turnList = new ArrayList<SnakePoint>();

    public Point foodPoint = new Point();

    public Main main;

    public MainCanvas(Main main) {
        super();
        this.main = main;

        gameStatus = GameStatus.prepare;
        //初始化蛇
        for (int i = 2; i >= 0; i--) {
            SnakePoint point = new SnakePoint(i, 15, this);
            point.currentStatus = SnakeStatus.RIGHT;
            point.name = i + "";
            snakeList.add(point);
        }

        createRandomFood();
    }

    @Override
    public void paint(Graphics g) {
        render(g);
    }


    public void run() {
        while (Boolean.TRUE) {
            try {
                long start = System.currentTimeMillis();
                if (gameStatus == GameStatus.running) {
                    repaint();
                }
                long end = System.currentTimeMillis();
                long cost = end - start;
//                System.out.println("cost = " + cost);
                Thread.sleep(GameSetting.speed);
            } catch (InterruptedException ex) {
                Logger.getLogger(MainCanvas.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }

    public void render(Graphics g) {
        readerBound(g);
        //如果游戏在运行状态中
        readerSnake(g);

        readerFood(g);
    }

    public void readerBound(Graphics g) {
        g.setColor(Color.BLACK);
        g.drawRect(GameSetting.GAME_AREA_START_X
                , GameSetting.GAME_AREA_START_Y
                , GameSetting.GAME_AREA_MAX_X
                , GameSetting.GAME_AREA_MAX_Y);
    }

    public void readerSnake(Graphics g) {
        g.setColor(Color.RED);
        SnakePoint create = null;
        int j = snakeList.size();
        for (int i = 0; i < j; i++) {
            SnakePoint snakePoint = snakeList.get(i);
            g.fillRect(GameSetting.GAME_AREA_START_X + (snakePoint.x * GameSetting.SNAKE_PIXEL)
                    , GameSetting.GAME_AREA_START_Y + (snakePoint.y * GameSetting.SNAKE_PIXEL)
                    , GameSetting.SNAKE_PIXEL, GameSetting.SNAKE_PIXEL);
            snakePoint.moveTurn(turnList);
            current_x = snakeList.get(0).x;
            current_y = snakeList.get(0).y;
            if (snakePoint.checkOutBound()) {
                gameStatus = GameStatus.pause;
            }
            if (i == 0) {
                if (foodPoint != null && snakePoint.x == foodPoint.x && snakePoint.y == foodPoint.y) {
                    SnakePoint adder = snakeList.get(snakeList.size() - 1);
                    int tmpX = adder.x;
                    int tmpY = adder.y;
                    create = new SnakePoint(tmpX, tmpY, this);
                    create.currentStatus = adder.currentStatus;
                    snakeList.add(create);
                    createRandomFood();
                }
            }
        }

        if(checkSnake()){
            gameStatus = GameStatus.pause;
        }

    }


    public boolean checkSnake(){
        SnakePoint header = snakeList.get(0);

        for(int i=1;i<snakeList.size();i++){
            SnakePoint snake = snakeList.get(i);
            if(header.x==snake.x&&header.y==snake.y){
                return true;
            }
        }

        return false;
    }


    public void readerFood(Graphics g) {
        if (foodPoint != null) {
            g.setColor(Color.BLUE);
            g.fillRect(GameSetting.GAME_AREA_START_X + (foodPoint.x * GameSetting.SNAKE_PIXEL)
                    , GameSetting.GAME_AREA_START_Y + (foodPoint.y * GameSetting.SNAKE_PIXEL), GameSetting.SNAKE_PIXEL, GameSetting.SNAKE_PIXEL);
        }
    }

    public void actionPerformed(ActionEvent e) {
        Object source = e.getSource();
        if (source == main.start) {
            gameStatus = GameStatus.running;
        } else if (source == main.end) {
            gameStatus = GameStatus.pause;
        } else if (source == main.right) {
            right();
        } else if (source == main.left) {
            left();
        } else if (source == main.up) {
            up();
        } else if (source == main.down) {
            down();
        }
    }

    public void up() {
        if (snakeList.get(0).currentStatus != SnakeStatus.DOWN) {
            setOrientation(SnakeStatus.UP);
        }
    }

    public void down() {
        if (snakeList.get(0).currentStatus != SnakeStatus.UP) {
            setOrientation(SnakeStatus.DOWN);
        }
    }

    public void left() {
        if (snakeList.get(0).currentStatus != SnakeStatus.RIGHT) {
            setOrientation(SnakeStatus.LEFT);
        }
    }

    public void right() {
        if (snakeList.get(0).currentStatus != SnakeStatus.LEFT) {
            setOrientation(SnakeStatus.RIGHT);
        }
    }

    private void setOrientation(SnakeStatus snakeStatus) {
        SnakePoint snakePoint = new SnakePoint(current_x, current_y, this);
        snakePoint.currentStatus = snakeStatus;
        turnList.add(snakePoint);

    }

    public void createRandomFood() {
        Map<Integer, Integer> xMap = new HashMap<Integer, Integer>();
        for (int i = 0; i < GameSetting.GAME_AREA_MAX_X / GameSetting.SNAKE_PIXEL; i++) {
            xMap.put(i, i);
        }
        for (int i = 0; i < snakeList.size(); i++) {
            int snakex = snakeList.get(i).x;
            if (xMap.get(snakex) != null)
                xMap.remove(snakex);
        }

        Map<Integer, Integer> yMap = new HashMap<Integer, Integer>();
        for (int i = 0; i < GameSetting.GAME_AREA_MAX_Y / GameSetting.SNAKE_PIXEL; i++) {
            yMap.put(i, i);
        }
        for (int i = 0; i < snakeList.size(); i++) {
            int snakey = snakeList.get(i).y;
            if (yMap.get(snakey) != null) {
                yMap.remove(snakey);
            }
        }


        int randomX = new Random().nextInt(xMap.size() - 1);
        foodPoint.x = randomX;

        int randomY = new Random().nextInt(yMap.size() - 1);
        foodPoint.y = randomY;
    }


    public void keyTyped(KeyEvent e) {

    }


    public void keyPressed(KeyEvent e) {
        if (e.getKeyCode() == KeyEvent.VK_ENTER) {
            if (gameStatus != GameStatus.running) {
                gameStatus = GameStatus.running;
            } else {
                gameStatus = GameStatus.pause;
            }
        } else if (e.getKeyCode() == KeyEvent.VK_UP) {
            up();
        } else if (e.getKeyCode() == KeyEvent.VK_DOWN) {
            down();
        } else if (e.getKeyCode() == KeyEvent.VK_LEFT) {
            left();
        } else if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
            right();
        }
    }

    public void keyReleased(KeyEvent e) {
    }
}
